package qs.controls
{
	import flash.geom.Point;
	import flash.display.DisplayObject;
	import mx.core.IUIComponent;
	import mx.core.Application;

	public class CircleLayout extends Layout
	{
		// ILayout interface		
		override public function getMeasuredSize():Point
		{
			return getMaxSize();
		}
		
		override public function findItemAt(px:Number, py:Number, seamAligned:Boolean):Number
		{
			// Can't execute this if we aren't attached to a container.
			if (!container || container.renderers.length == 0)
				return NaN;
				
			// Get the radius and center of the circle.
			var radius : Number = Math.min(unscaledContainerWidth, unscaledContainerHeight) / 2;
			var hCenter : Number = unscaledContainerWidth / 2;
			var vCenter : Number = unscaledContainerHeight / 2;
			
			var angle : Number = Math.atan2(py-vCenter, px-hCenter);
			if (angle < 0)
				angle += 2 * Math.PI;

			// figure out the closest "item" by working backwards from the angle to the index, using floating point math.
			var result : Number = container.renderers.length * angle / (2 * Math.PI);

			// depending on whether this is seam aligned, do a ceil or round.			
			result = (seamAligned) ? Math.ceil(result) : Math.round(result);
			
			// do a modulo op to make sure that this is within [0, length-1]. Modulo is the correct
			// operator in this case because this is a circle.
			result %= container.renderers.length;
			return result;
		}
		
		override public function generateLayout():void
		{
			// Get the radius and center of the circle.
			var radius : Number = Math.min(unscaledContainerWidth, unscaledContainerHeight) / 2;
			var hCenter : Number = unscaledContainerWidth / 2;
			var vCenter : Number = unscaledContainerHeight / 2;

			// Find the max item size.
			var maxSize : Point = getMaxSize();
			var max : Number = Math.max(maxSize.x, maxSize.y);
			
			// Inset the radius by the max size.
			radius -= max;

			// Loop through the items and position them.
			var length : int = container.renderers.length;
			for (var idx:int = 0; idx < length; idx++)
			{
				var renderer:IUIComponent = container.renderers[idx];
				var target:LayoutTarget = animator.targetFor(renderer);//targets[idx];
				
				// evenly space each item over 2*pi radians.
				var angle : Number = (2 * Math.PI) * idx / length;
				
				// position items on a circle.
				target.scaleX = target.scaleY = 1;
				target.item = renderer;
				target.unscaledWidth = renderer.getExplicitOrMeasuredWidth();
				target.unscaledHeight = renderer.getExplicitOrMeasuredHeight();
				target.x = hCenter + radius * Math.cos(angle) - target.unscaledWidth/2;
				target.y = vCenter + radius * Math.sin(angle) - target.unscaledHeight/2;
				target.animate = true;					
			}
			
			// If there is more than one item, and if there is a drag raget, nudge the items next to the drag target
			if (length > 1 && container.dragTargetIndex >= 0 && container.dragTargetIndex < length)
			{
				// Find the items to the left and right of the target.
				var leftIndex : int = (container.dragTargetIndex + length - 1) % length;
				var rightIndex : int = (leftIndex + 1) % length;
				
				var leftTarget : LayoutTarget = animator.targetFor(container.renderers[leftIndex]);
				var rightTarget : LayoutTarget = animator.targetFor(container.renderers[rightIndex]);
				
				// exaggerate the difference between the two targets by a factor of maxSize/2.
				var dx : Number = rightTarget.x - leftTarget.x;
				var dy : Number = rightTarget.y - leftTarget.y;
				var distance : Number = Math.sqrt( dx*dx + dy*dy );
				
				leftTarget.x -= dx / distance * max/2;
				leftTarget.y -= dy / distance * max/2;
				rightTarget.x += dx / distance * max/2;
				rightTarget.y += dy / distance * max/2;
			}
		}
		
		protected function getMaxSize() : Point
		{
			// Can't execute this if we aren't attached to a container.
			if (!container)
				return new Point(0, 0);
				
			// Find the max item size.
			var maxWidth : Number = 0;
			var maxHeight : Number = 0;
			
			if(container.renderers.length > 0)
			{
				for(var i:int=0;i<container.renderers.length;i++)
				{
					var itemRenderer:IUIComponent = container.renderers[i];
					maxWidth = Math.ceil(Math.max(maxWidth,itemRenderer.getExplicitOrMeasuredWidth()));
					maxHeight = Math.ceil(Math.max(maxHeight,itemRenderer.getExplicitOrMeasuredHeight()));
				}
			}
	
			return new Point(maxWidth, maxHeight);
		}
	}
}